using System;
using UnityEngine;
using UnityEngine.Playables;

namespace Taco.Timeline
{
    [ScriptGuid("c76545f3ff0961e4ba4395d075f7c341"), IconGuid("76c9ab52db448f24ba098ad7d930fd96"), Ordered(1), Color(165, 032, 025)]
    public class GameObjectTrack : Track<TimelineGameObjectClipPlayable>
    {
        public override void Bind()
        {
            TrackPlayable = Playable.Create(Timeline.PlayableGraph, Clips.Count);
            base.Bind();
        }

#if UNITY_EDITOR
        public override Type ClipType => typeof(GameObjectClip);

        public override Clip AddClip(UnityEngine.Object referenceObject, int frame)
        {
            GameObjectClip clip = new GameObjectClip(referenceObject as GameObject, this, frame);
            m_Clips.Add(clip);
            return clip;
        }
        public override bool DragValid()
        {
            return UnityEditor.DragAndDrop.objectReferences.Length == 1 && UnityEditor.DragAndDrop.objectReferences[0] is GameObject gameObject && UnityEditor.EditorUtility.IsPersistent(gameObject);
        }
#endif
    }

    [ScriptGuid("c76545f3ff0961e4ba4395d075f7c341"), Color(165, 032, 025)]
    public class GameObjectClip : Clip
    {
        [ShowInInspector, OnValueChanged("OnClipChanged", "RebindTimeline")]
        public GameObject GameObject;
        [ShowInInspector, OnValueChanged("RebindTimeline")]
        public string SocketName;

        public GameObjectClip(Track track, int frame) : base(track, frame)
        {
        }
        public GameObjectClip(GameObject gameObject, Track track, int frame) : base(track, frame)
        {
            GameObject = gameObject;
        }

#if UNITY_EDITOR

        public override string Name => GameObject ? GameObject.name : base.Name;
        public override ClipCapabilities Capabilities => ClipCapabilities.Resizable;

        void OnClipChanged()
        {
            OnNameChanged?.Invoke();
        }
#endif
    }

    public class TimelineGameObjectClipPlayable : TimelineClipPlayable
    {
        GameObjectClip GameObjectClip;
        GameObject GameObject;

        public TimelineGameObjectClipPlayable() { }

        public override void Initialize(Clip clip, Playable owner, Timeline timeline)
        {
            base.Initialize(clip, owner, timeline);

            GameObjectClip = clip as GameObjectClip;
            timeline.OnRebind += Destroy;
        }

        public override void OnEnable()
        {
            base.OnEnable();
            Instantiate();
        }
        public override void OnDisable()
        {
            base.OnDisable();
            Destroy();
        }
        public override void OnDestroy()
        {
            base.OnDestroy();
            Destroy();
        }

        void Instantiate()
        {
            if (GameObjectClip.GameObject)
            {
                Transform socketTransform = Timeline.TimelinePlayer.transform;
                var childTransforms = Timeline.TimelinePlayer.GetComponentsInChildren<Transform>();
                foreach (var childTransform in childTransforms)
                {
                    if(childTransform.name == GameObjectClip.SocketName)
                    {
                        socketTransform = childTransform;
                        break;
                    }
                }

                GameObject = UnityEngine.Object.Instantiate(GameObjectClip.GameObject, socketTransform, false);
            }
        }
        void Destroy()
        {
            if (GameObject)
            {
                UnityEngine.Object.DestroyImmediate(GameObject);
                GameObject = null;
            }
        }
    }
}